// $Header: $

using System;
using System.Data;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;

namespace LogParser
{
    /// <summary>
    /// Summary description for LogParser.Parser.
    /// </summary>
    public class Parser
    {
        #region Private Member Variables


        private List<string> _logLines;
        private Player _actingPlayer;
        private Round _activeRound;
        private Hashtable _playerList;
        private Match _match;

        private List<ChatLog> _chatList;
        private List<Kill> _killList;
        private List<Suicide> _suicideList;
        private List<MedicCharge> _medicChargeList;
        private List<Engineering> _engineeringList;
        private List<Destruction> _destructionList;
        private List<Domination> _dominationList;
        private List<Revenge> _revengeList;
        private List<Flag> _flagEventList;
        private List<Capture> _captureEventList;
        private List<CaptureBlock> _captureBlockEventList;
        private List<Round> _roundList;

        private DateTime _eventDateTime;

        private int _leagueId;

        #endregion
        string tempworkingline;

        #region Constructor
        /// <summary>
        /// Initializes a new instance of the <see cref="Parser"/> class.
        /// </summary>
        public Parser()
        {
            //
            // TODO: Add constructor logic here
            //
        }

        public Parser( string logFile, int leagueId )
        {
            _logLines = new List<string>();
            _leagueId = leagueId;

            StreamReader SR;
            string S;
            SR = File.OpenText( logFile );
            S = SR.ReadLine();
            while ( S != null )
            {
                _logLines.Add( S );
                S = SR.ReadLine();
            }
            SR.Close();

            _activeRound = new Round();
            _match = new Match();

            _match.LogFilePath = logFile;

            if ( _match.LogFileName.Contains( @"/" ) )
                _match.LogFileName = logFile.Substring( logFile.LastIndexOf( @"/" ) + 1 );
            else
                _match.LogFileName = logFile.Substring( logFile.LastIndexOf( @"\" ) + 1 );

            _playerList = new Hashtable();
            _chatList = new List<ChatLog>();
            _killList = new List<Kill>();
            _suicideList = new List<Suicide>();
            _medicChargeList = new List<MedicCharge>();
            _engineeringList = new List<Engineering>();
            _destructionList = new List<Destruction>();
            _dominationList = new List<Domination>();
            _revengeList = new List<Revenge>();
            _flagEventList = new List<Flag>();
            _captureEventList = new List<Capture>();
            _captureBlockEventList = new List<CaptureBlock>();
            _roundList = new List<Round>();
        }

        #endregion

        #region Public Properties

        public DateTime EventDateTime
        {
            get
            {
                return _eventDateTime;
            }
            set
            {
                _eventDateTime = value;
            }
        }

        public List<ChatLog> ChatList
        {
            get { return _chatList; }
        }

        public List<Kill> KillList
        {
            get { return _killList; }
        }

        public Hashtable PlayerList
        {
            get { return _playerList; }
        }

        public List<Suicide> SuicideList
        {
            get { return _suicideList; }
        }

        public List<MedicCharge> MedicChargeList
        {
            get { return _medicChargeList; }
        }

        public List<Engineering> EngineeringList
        {
            get { return _engineeringList; }
        }

        public List<Destruction> DestructionList
        {
            get { return _destructionList; }
        }

        public List<Domination> DominationList
        {
            get { return _dominationList; }
        }

        public List<Revenge> RevengeList
        {
            get { return _revengeList; }
        }

        public List<Flag> FlagEventList
        {
            get { return _flagEventList; }
        }

        public List<Capture> CaptureEventList
        {
            get { return _captureEventList; }
        }

        public List<CaptureBlock> CaptureBlockEventList
        {
            get { return _captureBlockEventList; }
        }

        public List<Round> RoundList
        {
            get { return _roundList; }
        }

        public Match Match
        {
            get { return _match; }
        }

        public int LeagueId
        {
            get { return _leagueId; }

        }

        #endregion

        #region Private Properties

        #endregion

        #region Public Member Functions

        public void Parse()
        {
            bool roundStarted = false;

            for ( int i = 0; i < _logLines.Count; i++ )
            {
                string workingLine = _logLines[ i ];
                tempworkingline = workingLine;
                Console.WriteLine( "LINE " + i + ": " + workingLine );

                if ( i < ( _logLines.Count - 1 ) )
                {
                    if ( _logLines[ i + 1 ].Substring( 0, 1 ) != "L" )
                    {
                        workingLine = workingLine + _logLines[ i + 1 ];
                        _logLines[ i + 1 ] = string.Empty;
                    }
                }



                if ( workingLine != string.Empty )
                {
                    // get datetime for the event
                    EventDateTime = GetDateTime( ref workingLine );

                    if ( workingLine.Contains( "World triggered \"Round_Start\"" ) )
                    {
                        if ( _match.MatchStartTime == new DateTime() )
                        {
                            _match.MatchStartTime = EventDateTime;
                        }

                        roundStarted = true;



                    }

                    if ( roundStarted == true )
                    {
                        if ( CheckIfPlayerEvent( workingLine ) )
                        {
                            // Process player event
                            ProcessPlayerEvent( ref workingLine );
                        }
                        else if ( CheckIfTeamEvent( workingLine ) )
                        {
                            // Process team event
                            ProcessTeamEvent( ref workingLine );
                        }
                        else if ( CheckIfWorldEvent( workingLine ) )
                        {
                            // Process world event
                            ProcessWorldEvent( ref workingLine );
                        }

                    }
                    else
                    {
                        if ( CheckIfPlayerEvent( workingLine ) )
                        {
                            // Process player event
                            ProcessPlayerEvent_PreRoundStart( ref workingLine );
                        }
                    }
                }
            }

        }


        #region Event Processing

        #region Player Events

        private bool CheckIfPlayerEvent( string workingLine )
        {
            return CheckIfMatch( workingLine, RegularExpressions.PLAYEREVENT );
        }

        private void ProcessPlayerEvent( ref string workingLine )
        {
            string actingPlayerId = GetPlayer( ref workingLine, true );
            _actingPlayer = (Player) _playerList[ actingPlayerId ];

            if ( CheckIfSayEvent( workingLine ) )
            {
                ProcessSayEvent( ref workingLine );
            }
            else if ( CheckIfKillEvent( workingLine ) )
            {
                ProcessKillEvent( ref workingLine );
            }
            else if ( CheckIfChangeClassEvent( workingLine ) )
            {
                ProcessChangeClassEvent( ref workingLine );
            }
            else if ( CheckIfSuicideEvent( workingLine ) )
            {
                ProcessSuicideEvent( ref workingLine );
            }
            else if ( CheckIfTriggeredEvent( workingLine ) )
            {
                // Process world event
                ProcessTriggeredEvent( ref workingLine );
            }

        }

        private void ProcessPlayerEvent_PreRoundStart( ref string workingLine )
        {
            string actingPlayerId = GetPlayer( ref workingLine, true );
            _actingPlayer = (Player) _playerList[ actingPlayerId ];

            if ( CheckIfChangeClassEvent( workingLine ) )
            {
                ProcessChangeClassEvent( ref workingLine );
            }
        }


        #region Suicides

        private bool CheckIfSuicideEvent( string workingLine )
        {
            return CheckIfMatch( workingLine, RegularExpressions.EVENT_SUICIDE );
        }

        // L 08/24/2008 - 18:32:56: "[Ars.UPorn]Verio<106><STEAM_0:1:3602481><Red>" committed suicide with "tf_projectile_pipe_remote" (attacker_position "1058 3458 432")
        private void ProcessSuicideEvent( ref string workingLine )
        {
            workingLine = workingLine.Replace( "committed suicide with \"", "" );
            workingLine = workingLine.Trim();
            string weaponName = workingLine.Substring( 0, workingLine.IndexOf( "\"" ) );

            workingLine = workingLine.Replace( weaponName + "\"", "" );
            workingLine = workingLine.Trim();

            Position suicidePosition = GetPosition( ref workingLine );


            Suicide newSuicide = new Suicide();
            newSuicide.DateTime = EventDateTime;
            newSuicide.Player = _actingPlayer;
            newSuicide.SuicidePosition = suicidePosition;
            newSuicide.WeaponName = weaponName;

            newSuicide.ClassName = _actingPlayer.CurrentClass;

            _suicideList.Add( newSuicide );

        }

        #endregion

        #region Class Change

        private void ProcessChangeClassEvent( ref string workingLine )
        {
            //changed role to 
            workingLine = workingLine.Replace( "changed role to ", "" );
            workingLine = workingLine.Replace( "\"", "" );
            workingLine = workingLine.Trim();

            string newClass = workingLine;

            string currentPlayerId = _actingPlayer.PlayerId;

            _actingPlayer.CurrentClass = newClass;

            if ( _actingPlayer.ClassList.Contains( newClass ) == false )
                _actingPlayer.ClassList.Add( newClass );


            UpdateExistingPlayer( currentPlayerId );

            workingLine = string.Empty;
        }



        private bool CheckIfChangeClassEvent( string workingLine )
        {
            return CheckIfMatch( workingLine, RegularExpressions.EVENT_CHANGECLASS );
        }

        #endregion

        #region Say Event

        private void ProcessSayEvent( ref string workingLine )
        {
            ChatLog chatItem = new ChatLog();


            string tempLine = GetDataSection( ref workingLine, RegularExpressions.EVENT_SAY_TEAM );


            if ( tempLine == string.Empty )
            {
                tempLine = GetDataSection( ref workingLine, RegularExpressions.EVENT_SAY );
                chatItem.ChatType = "say";
            }
            else
            {
                chatItem.ChatType = "say_team";
            }

            tempLine = tempLine.Replace( chatItem.ChatType, "" );
            tempLine = tempLine.Replace( "\"", "" );
            tempLine = tempLine.Trim();

            chatItem.Text = tempLine;
            chatItem.DateTime = EventDateTime;
            chatItem.PlayerInfo = _actingPlayer;
            chatItem.Team = _actingPlayer.Team;

            _chatList.Add( chatItem );

            workingLine = string.Empty;  // Event is done

        }

        private bool CheckIfSayEvent( string workingLine )
        {

            bool result = CheckIfMatch( workingLine, RegularExpressions.EVENT_SAY );

            if ( result == false )
            {
                result = CheckIfMatch( workingLine, RegularExpressions.EVENT_SAY_TEAM );
            }

            return result;
        }

        #endregion

        #region Kill Event + Kill Assists

        // L 08/24/2008 - 18:44:28: "[Ars.NSFW] medina! [Wiggles]<103><STEAM_0:1:3813495><Blue>" killed "[Ars.UPorn]Verio<106><STEAM_0:1:3602481><Red>"
        // with "sniperrifle" (customkill "headshot") (attacker_position "-1151 -224 244") (victim_position "830 -95 296")
        private void ProcessKillEvent( ref string workingLine )
        {
            Kill newKill = new Kill();

            //string tempLine = GetDataSection( ref workingLine, RegularExpressions.EVENT_KILL );
            workingLine = workingLine.Replace( "killed ", "" );

            string victimPlayerId = GetPlayer( ref workingLine, false );
            Player victimPlayer = (Player) _playerList[ victimPlayerId ];

            workingLine = workingLine.Replace( "with \"", "" );

            string weaponType = workingLine.Substring( 0, workingLine.IndexOf( "\"" ) );
            workingLine = workingLine.Replace( weaponType + "\"", "" );
            workingLine = workingLine.Trim();

            string customKill = string.Empty;

            if ( workingLine.Contains( "customkill" ) )
            {
                // Handle headshots and such here

                workingLine = workingLine.Replace( "(customkill \"", "" );
                customKill = workingLine.Substring( 0, workingLine.IndexOf( "\"" ) );
                workingLine = workingLine.Replace( customKill + "\")", "" );
                workingLine = workingLine.Trim();
            }

            Position attackerPosition = GetPosition( ref workingLine );
            Position victimPostion = GetPosition( ref workingLine );

            newKill.Attacker = _actingPlayer;
            newKill.Victim = victimPlayer;
            newKill.KillTime = EventDateTime;
            newKill.Weapon = weaponType;
            newKill.CustomKill = customKill;
            newKill.AttackerPosition = attackerPosition;
            newKill.VictimPosition = victimPostion;

            newKill.AttackerClass = _actingPlayer.CurrentClass;
            newKill.VictimClass = victimPlayer.CurrentClass;

            newKill.AttackerTeam = _actingPlayer.Team;
            newKill.VictimTeam = victimPlayer.Team;


            // log id
            // mapid

            // roundid
            // miniroundid


            _killList.Add( newKill );


        }

        private bool CheckIfKillEvent( string workingLine )
        {
            return CheckIfMatch( workingLine, RegularExpressions.EVENT_KILL );
        }

        #endregion

        #region Triggered Event

        // triggered "flagevent" (event "picked up") (position "-3016 -1536 -281")
        // triggered "flagevent" (event "defended") (position "-2988 -238 -127")
        // triggered "flagevent" (event "dropped") (position "-3057 -1524 -281")
        // triggered "flagevent" (event "captured") (position "-2922 -1412 -261")
        // L 08/24/2008 - 18:48:02: "[Ars.NSFW]medbot^5 [Wiggles]<94><STEAM_0:1:349209><Blue>" triggered "captureblocked" (cp "1") (cpname "#Badlands_cap_blue_cp2") (position "-2005 -1676 396")
        private bool CheckIfTriggeredEvent( string workingLine )
        {
            return CheckIfMatch( workingLine, RegularExpressions.EVENT_TRIGGERED );
        }

        private void ProcessTriggeredEvent( ref string workingLine )
        {
            if ( CheckIfChargeDeployed( workingLine ) )
            {
                ProcessChargeDeployed( ref workingLine );
            }
            else if ( CheckIfEngineering( workingLine ) )
            {
                ProcessEngineering( ref workingLine );
            }
            else if ( CheckIfDestruction( workingLine ) )
            {
                ProcessDestruction( ref workingLine );
            }
            else if ( CheckIfKillAssist( workingLine ) )
            {
                ProcessKillAssistEvent( ref workingLine );
            }
            else if ( CheckIfDomination( workingLine ) )
            {
                ProcessDomination( ref workingLine );
            }
            else if ( CheckIfRevenge( workingLine ) )
            {
                ProcessRevenge( ref workingLine );
            }
            else if ( CheckIfFlagEvent( workingLine ) )
            {
                ProcessFlagEvent( ref workingLine );
            }
            else if ( CheckIfCaptureBlocked( workingLine ) )
            {
                ProcessCaptureBlocked( ref workingLine );
            }


        }

        #region Capture Blocked - triggered "captureblocked"

        // L 08/24/2008 - 18:48:02: "[Ars.NSFW]medbot^5 [Wiggles]<94><STEAM_0:1:349209><Blue>" triggered "captureblocked" (cp "1") (cpname "#Badlands_cap_blue_cp2") (position "-2005 -1676 396")
        private void ProcessCaptureBlocked( ref string workingLine )
        {

            string tempLine = GetDataSection( ref workingLine, RegularExpressions.EVENT_TRIGGERED_CAPTUREBLOCKED );

            int cpNumber = GetCPNumber( ref workingLine );
            string cpName = GetCPName( ref workingLine );

            CaptureBlock newBlock = new CaptureBlock();
            newBlock.CPName = cpName;
            newBlock.CPNumber = cpNumber;
            newBlock.DateTime = EventDateTime;
            newBlock.Player = _actingPlayer;
            newBlock.Team = _actingPlayer.Team;

            _captureBlockEventList.Add( newBlock );

        }

        private bool CheckIfCaptureBlocked( string workingLine )
        {
            return CheckIfMatch( workingLine, RegularExpressions.EVENT_TRIGGERED_CAPTUREBLOCKED );
        }

        #endregion

        #region Flag Event - triggered "flagevent"

        private bool CheckIfFlagEvent( string workingLine )
        {
            return CheckIfMatch( workingLine, RegularExpressions.EVENT_TRIGGERED_FLAGEVENT );
        }

        // triggered "flagevent" (event "picked up") (position "-3016 -1536 -281")
        // triggered "flagevent" (event "defended") (position "-2988 -238 -127")
        // triggered "flagevent" (event "dropped") (position "-3057 -1524 -281")
        // triggered "flagevent" (event "captured") (position "-2922 -1412 -261")
        private void ProcessFlagEvent( ref string workingLine )
        {

            string tempLine = GetDataSection( ref workingLine, RegularExpressions.EVENT_TRIGGERED_FLAGEVENT );
            string eventType = GetDataSection( ref workingLine, RegularExpressions.WORLD_EVENT );

            eventType = eventType.Replace( "(event \"", "" );
            eventType = eventType.Replace( "\")", "" );
            eventType = eventType.Trim();

            Position flagPosition = new Position();
            flagPosition = GetPosition( ref workingLine );

            Flag newFlag = new Flag();
            newFlag.DateTime = EventDateTime;
            newFlag.EventType = eventType;
            newFlag.Player = _actingPlayer;
            newFlag.Position = flagPosition;

            _flagEventList.Add( newFlag );
        }

        #endregion

        #region Revenge - triggered "revenge" against

        private bool CheckIfRevenge( string workingLine )
        {
            return CheckIfMatch( workingLine, RegularExpressions.EVENT_TRIGGERED_REVENGE );
        }

        // L 08/24/2008 - 18:53:41: "[Ars.UP] Puddin' [Wiggles]<108><STEAM_0:1:17834846><Red>" triggered "revenge" against "Opposable<112><STEAM_0:1:16198379><Blue>" (assist "1")
        private void ProcessRevenge( ref string workingLine )
        {
            string tempLine = GetDataSection( ref workingLine, RegularExpressions.EVENT_TRIGGERED_REVENGE );

            string victimPlayerId = GetPlayer( ref workingLine, false );
            Player victimPlayer = (Player) _playerList[ victimPlayerId ];

            string weaponName = _killList[ _killList.Count - 1 ].Weapon;

            Revenge newRevenge = new Revenge();
            newRevenge.DateTime = EventDateTime;
            newRevenge.RevengingPlayer = _actingPlayer;
            newRevenge.VictimPlayer = victimPlayer;
            newRevenge.WeaponName = weaponName;

            _revengeList.Add( newRevenge );


        }

        #endregion

        #region Domination - triggered "domination" against

        private bool CheckIfDomination( string workingLine )
        {
            return CheckIfMatch( workingLine, RegularExpressions.EVENT_TRIGGERED_DOMINATION );
        }

        // L 08/24/2008 - 18:54:33: "[Ars] Zyrxil<105><STEAM_0:0:5026980><Red>" triggered "domination" against "[Ars.NSFW] medina! [Wiggles]<103><STEAM_0:1:3813495><Blue>"
        private void ProcessDomination( ref string workingLine )
        {
            string tempLine = GetDataSection( ref workingLine, RegularExpressions.EVENT_TRIGGERED_DOMINATION );

            string victimPlayerId = GetPlayer( ref workingLine, false );
            Player victimPlayer = (Player) _playerList[ victimPlayerId ];

            Domination newDomination = new Domination();
            newDomination.DateTime = EventDateTime;
            newDomination.DominatingPlayer = _actingPlayer;
            newDomination.VictimPlayer = victimPlayer;
            newDomination.WeaponName = _killList[ _killList.Count - 1 ].Weapon;  // get weapon from previous kill

            _dominationList.Add( newDomination );
        }

        #endregion

        #region Kill Assist -- triggered "kill assist" against

        // triggered "kill assist" against "[CSTF]Comic<15><STEAM_0:0:3448133><Red>" 
        // (assister_position "-2614 -1316 -255") (attacker_position "-2587 -1530 -230") (victim_position "-2921 -1619 -287")
        private void ProcessKillAssistEvent( ref string workingLine )
        {
            string tempLine = GetDataSection( ref workingLine, RegularExpressions.EVENT_TRIGGERED_KILLASSIST );

            string victimPlayer = GetPlayer( ref workingLine, false );
            Position assistPosition = GetPosition( ref workingLine );


            Assist newAssist = new Assist();

            newAssist.AssistClassName = _actingPlayer.CurrentClass;
            newAssist.AssistPlayer = _actingPlayer;
            newAssist.AssistPosition = assistPosition;
            newAssist.DateTime = EventDateTime;
            newAssist.Type = Assist.AssistType.Kill;

            // update the last kill
            Kill lastKill = _killList[ _killList.Count - 1 ];
            lastKill.Assists.Add( newAssist );
            _killList[ _killList.Count - 1 ] = lastKill;

            workingLine = string.Empty;

        }

        private bool CheckIfKillAssist( string workingLine )
        {
            return CheckIfMatch( workingLine, RegularExpressions.EVENT_TRIGGERED_KILLASSIST );
        }

        #endregion

        #region Destruction -- triggered "killedobject"

        private bool CheckIfDestruction( string workingLine )
        {
            return CheckIfMatch( workingLine, RegularExpressions.EVENT_TRIGGERED_KILLEDOBJECT );
        }

        private bool CheckIfDestructionAssist( string workingLine )
        {
            return CheckIfMatch( workingLine, RegularExpressions.EVENT_TRIGGERED_KILLEDOBJECT_ASSIST );
        }

        // triggered "killedobject" (object "OBJ_SENTRYGUN") (weapon "shotgun_soldier") (objectowner "|RES|Stinkfist<26><STEAM_0:1:229390><Blue>") (attacker_position "-2606 -1010 -84")
        private void ProcessDestruction( ref string workingLine )
        {


            string tempLine = GetDataSection( ref workingLine, RegularExpressions.EVENT_TRIGGERED_KILLEDOBJECT );

            string objectName = GetObject( ref workingLine );
            string weaponName = GetWeapon( ref workingLine );
            Player objectOwner = GetObjectOwner( ref workingLine );

            if ( CheckIfDestructionAssist( workingLine ) )
            {
                ProcessDestructionAssist( ref workingLine );
            }
            else
            {

                Position attackerPosition = GetPosition( ref workingLine );

                Destruction newDestruction = new Destruction();
                newDestruction.DateTime = EventDateTime;
                newDestruction.AttackerPosition = attackerPosition;
                newDestruction.AttackingPlayer = _actingPlayer;
                newDestruction.ObjectName = objectName;
                newDestruction.VictimPlayer = objectOwner;
                newDestruction.WeaponName = weaponName;

                _destructionList.Add( newDestruction );
            }
        }

        private void ProcessDestructionAssist( ref string workingLine )
        {
            Assist newAssist = new Assist();

            string tempLine = GetDataSection( ref workingLine, RegularExpressions.EVENT_TRIGGERED_KILLEDOBJECT_ASSIST );

            newAssist.AssistPlayer = _actingPlayer;
            newAssist.AssistPosition = GetPosition( ref workingLine );
            newAssist.Type = Assist.AssistType.Destruction;
            newAssist.DateTime = EventDateTime;
            newAssist.AssistClassName = _actingPlayer.CurrentClass;

            Destruction recentDestruction = _destructionList[ _destructionList.Count - 1 ];

            recentDestruction.Assists.Add( newAssist );

            _destructionList[ _destructionList.Count - 1 ] = recentDestruction;

        }

        #endregion

        #region Engineering (built)  -- triggered "builtobject"

        // triggered "builtobject" (object "OBJ_SENTRYGUN") (position "-2322 -807 -255")
        private bool CheckIfEngineering( string workingLine )
        {
            return CheckIfMatch( workingLine, RegularExpressions.EVENT_TRIGGERED_BUILTOBJECT );
        }

        private void ProcessEngineering( ref string workingLine )
        {
            string tempLine = GetDataSection( ref workingLine, RegularExpressions.EVENT_TRIGGERED_BUILTOBJECT );


            string objectName = GetObject( ref workingLine );
            Position placementPosition = GetPosition( ref workingLine );

            Engineering newEngineering = new Engineering();
            newEngineering.Player = _actingPlayer;
            newEngineering.ObjectBuilt = objectName;
            newEngineering.PlacementPosition = placementPosition;
            newEngineering.DateTime = EventDateTime;

            _engineeringList.Add( newEngineering );
        }


        #endregion

        #region Charge Deployed

        // triggered "chargedeployed"
        private bool CheckIfChargeDeployed( string workingLine )
        {
            //bool result = workingLine.Contains( "triggered \"chargedeployed\"" );

            //return result;

            return CheckIfMatch( workingLine, RegularExpressions.EVENT_TRIGGERED_CHARGEDEPLOYED );

        }

        private void ProcessChargeDeployed( ref string workingLine )
        {

            workingLine = workingLine.Replace( "triggered \"chargedeployed\"", "" );
            workingLine = workingLine.Trim();

            MedicCharge newCharge = new MedicCharge();

            newCharge.DateTime = EventDateTime;
            newCharge.EventType = "chargedeployed";
            newCharge.Player = _actingPlayer;

            _medicChargeList.Add( newCharge );
        }

        #endregion

        #endregion


        #endregion

        #region Team Event

        private void ProcessTeamEvent( ref string workingLine )
        {
            if ( CheckIfCapture( workingLine ) )
            {
                ProcessCapture( ref workingLine );
            }
            else if ( CheckIfFinalScore( workingLine ) )
            {
                ProcessFinalScore( ref workingLine );
            }
        }

        private bool CheckIfTeamEvent( string workingLine )
        {
            return CheckIfMatch( workingLine, RegularExpressions.TEAMEVENT );
        }

        #region Final Scores For Match

        // L 08/24/2008 - 19:03:59: Team "Red" final score "2" with "4" players
        // L 08/24/2008 - 19:03:59: Team "Blue" final score "3" with "5" players
        private void ProcessFinalScore( ref string workingLine )
        {
            string teamName = GetDataSection( ref workingLine, RegularExpressions.EVENT_TEAM_FINALSCORE );
            teamName = teamName.Substring( teamName.IndexOf( "\"" ) + 1 );
            teamName = teamName.Substring( 0, teamName.IndexOf( "\"" ) );

            string scoreLine = workingLine.Substring( 1 );
            scoreLine = scoreLine.Substring( 0, scoreLine.IndexOf( "\"" ) );

            int score = Convert.ToInt32( scoreLine );

            if ( teamName == "Blue" )
            {
                _match.BlueFinalScore = score;
            }
            else if ( teamName == "Red" )
            {
                _match.RedFinalScore = score;
            }

            
            _match.MatchEndTime = EventDateTime;

        }

        private bool CheckIfFinalScore( string workingLine )
        {
            bool isFinalScoreEvent = false;

            isFinalScoreEvent = CheckIfMatch( workingLine, RegularExpressions.EVENT_TEAM_FINALSCORE );

            return isFinalScoreEvent;
        }


        #endregion

        #region Capture - triggered "pointcaptured"

        // L 08/24/2008 - 18:54:52: Team "Blue" triggered "pointcaptured" (cp "4") (cpname "#Badlands_cap_red_cp1") 
        // (numcappers "1") (player1 "[Ars.NSFW]medbot^5 [Wiggles]<94><STEAM_0:1:349209><Blue>") (position1 "779 4169 0") 
        private void ProcessCapture( ref string workingLine )
        {
            Capture newCap = new Capture();

            string teamName = GetTeamName( ref workingLine );


            int cpNumber = GetCPNumber( ref workingLine );
            string cpName = GetCPName( ref workingLine );

            string numCappersString = GetDataSection( ref workingLine, RegularExpressions.WORLD_NUMCAPPERS );
            numCappersString = numCappersString.Replace( "(numcappers \"", "" );
            numCappersString = numCappersString.Replace( "\")", "" );
            numCappersString = numCappersString.Trim();

            int numCappers = Convert.ToInt32( numCappersString );

            for ( int i = 0; i < numCappers; i++ )
            {
                string playerId = string.Empty;
                string playerData = GetDataSection( ref workingLine, RegularExpressions.WORLD_CAPPERPLAYER );
                playerData = playerData.Substring( playerData.IndexOf( "\"" ) );
                playerData = playerData.Replace( ")", "" );

                playerId = GetPlayer( ref playerData, false );

                Player capPlayer = (Player) _playerList[ playerId ];

                Position throwAwayPostion = new Position();
                throwAwayPostion = GetPosition( ref workingLine );

                newCap.CapturingPlayerList.Add( capPlayer );
            }

            // finish here
            newCap.CPName = cpName;
            newCap.CPNumber = cpNumber;
            newCap.DateTime = EventDateTime;
            newCap.Team = teamName;

            _captureEventList.Add( newCap );

        }


        private bool CheckIfCapture( string workingLine )
        {
            return CheckIfMatch( workingLine, RegularExpressions.EVENT_TEAM_POINTCAPTURED );
        }

        #endregion


        #endregion

        #region World Events

        private void ProcessWorldEvent( ref string workingLine )
        {
            if ( CheckIfRoundWin( workingLine ) )
            {
                ProcessRoundWin( ref workingLine );
            }
            else if ( CheckIfRoundLength( workingLine ) )
            {
                ProcessRoundLength( ref workingLine );
            }

        }

        private bool CheckIfWorldEvent( string workingLine )
        {
            return CheckIfMatch( workingLine, RegularExpressions.WORLDEVENT );
        }

        #region Round_Win

        // L 08/24/2008 - 19:03:44: World triggered "Round_Win" (winner "Blue")
        // L 08/24/2008 - 19:03:44: World triggered "Round_Length" (seconds "126.41")
        private void ProcessRoundWin( ref string workingLine )
        {
            string tempLine = GetDataSection( ref workingLine, RegularExpressions.WORLD_ROUNDWIN );
            string winningTeam = GetDataSection( ref workingLine, RegularExpressions.WORLD_WINNER );

            winningTeam = winningTeam.Substring( winningTeam.IndexOf( "\"" ) + 1 );
            winningTeam = winningTeam.Substring( 0, winningTeam.LastIndexOf( "\"" ) );

            _activeRound.WinningTeam = winningTeam;

            // Add players to round at end
            foreach ( Player player in _playerList.Values )
            {
                if ( player.Team.ToUpper() == winningTeam.ToUpper() )
                    _activeRound.WinningTeamPlayers.Add( player );
            }

        }

        private bool CheckIfRoundWin( string workingLine )
        {
            return CheckIfMatch( workingLine, RegularExpressions.WORLD_ROUNDWIN );
        }

        #endregion

        #region Round_Length

        private void ProcessRoundLength( ref string workingLine )
        {
            string tempLine = GetDataSection( ref workingLine, RegularExpressions.WORLD_ROUNDLENGTH );
            string seconds = GetDataSection( ref workingLine, RegularExpressions.WORLD_SECONDS );
            seconds = seconds.Substring( seconds.IndexOf( "\"" ) + 1 );
            seconds = seconds.Substring( 0, seconds.LastIndexOf( "\"" ) );

            _activeRound.RoundLengthSeconds = Convert.ToDouble( seconds );
            _activeRound.EndTime = EventDateTime;

            _roundList.Add( _activeRound );

            _activeRound = new Round();
        }

        private bool CheckIfRoundLength( string workingLine )
        {
            return CheckIfMatch( workingLine, RegularExpressions.WORLD_ROUNDLENGTH );
        }

        #endregion

        #endregion

        #region Position Processing

        // 
        /// <summary>
        /// Reduces a position to its x,y,z coordinates.
        /// Example: '  ((type_)position(#) "-111 0 423")   ' would break into x=-111, y=0, z=423  (though they'd be really high in the air if that was the case)
        /// </summary>
        /// <param name="workingLine">Current log line being processed</param>
        /// <returns>Position object containing the coordinates</returns>
        private Position GetPosition( ref string workingLine )
        {
            Position returnPosition = new Position();

            try
            {
                string tempLine = GetDataSection( ref workingLine, RegularExpressions.WORLD_POSITION );
                tempLine = tempLine.Substring( tempLine.IndexOf( "position" ) - 1 );
                tempLine = tempLine.Substring( tempLine.IndexOf( "\"" ) + 1 );
                tempLine = tempLine.Substring( 0, tempLine.IndexOf( "\"" ) );

                string[] positionCoordinates = tempLine.Split( ' ' );

                returnPosition.X = Convert.ToDouble( positionCoordinates[ 0 ] );
                returnPosition.Y = Convert.ToDouble( positionCoordinates[ 1 ] );
                returnPosition.Z = Convert.ToDouble( positionCoordinates[ 2 ] );
            }
            catch
            {

            }
            return returnPosition;
        }


        #endregion


        #region Player Processing

        private string GetPlayer( ref string workingLine, bool setAsActingPlayer )
        {
            Player returnPlayer = new Player();

            string playerName = string.Empty;
            string playerTeam = string.Empty;
            string playerId = string.Empty;

            //PLAYERMATCH
            string tempLine = GetDataSection( ref workingLine, RegularExpressions.PLAYERMATCH );
            try
            {
                workingLine = workingLine.Replace( tempLine, "" );  // remove the matched data from the working line

                tempLine = tempLine.Substring( 1 );
                tempLine = tempLine.Substring( 0, tempLine.Length - 1 );

            }
            catch ( Exception ex )
            {
                return "";
            }
            playerName = tempLine.Substring( 0, tempLine.IndexOf( "<" ) );


            tempLine = tempLine.Replace( playerName, "" );

            string[] playerInfo = tempLine.Split( '>' );

            for ( int i = 0; i < 3; i++ )
                playerInfo[ i ] = playerInfo[ i ].Substring( 1 );

            playerId = playerInfo[ 1 ];
            playerTeam = playerInfo[ 2 ];




            returnPlayer.PlayerId = playerId;
            returnPlayer.Team = playerTeam;
            returnPlayer.LastSeen = EventDateTime;

            if ( returnPlayer.PlayerNames.Contains( playerName ) == false )
                returnPlayer.PlayerNames.Add( playerName );

            UpdatePlayerList( ref returnPlayer, playerName, playerId, playerTeam );

            if ( setAsActingPlayer )
                _actingPlayer = (Player) _playerList[ playerId ];

            workingLine = workingLine.Trim();  // strip extra space

            return playerId;
        }

        private void UpdatePlayerList( ref Player playerToUpdate, string playerName, string playerId, string playerTeam )
        {
            if ( _playerList.ContainsKey( playerId ) )
            {
                Player tempPlayer = (Player) _playerList[ playerId ];

                if ( tempPlayer.PlayerNames.Contains( playerName ) == false )
                    tempPlayer.PlayerNames.Add( playerName );

                tempPlayer.LastSeen = EventDateTime;
                tempPlayer.Team = playerTeam;

                _playerList[ playerId ] = tempPlayer;  // update list of names

            }
            else
            {
                playerToUpdate.FirstSeen = EventDateTime;

                _playerList.Add( playerId, playerToUpdate );  // add new player to the list
            }
        }

        private void UpdateExistingPlayer( string currentPlayerId )
        {
            if ( _playerList.ContainsKey( currentPlayerId ) )
            {
                Player currentPlayer = (Player) _playerList[ currentPlayerId ];

                _playerList[ currentPlayerId ] = currentPlayer;  // put the player back in the list

                _actingPlayer = currentPlayer;

            }
            else
            {
                // no player found...they shoudl have been in here already
                throw new Exception( "Expected to find player " + _actingPlayer.PlayerId + " - " + _actingPlayer.PlayerNames[ 0 ].ToString() +
                                        " but they were not found.  This should not occur." );
            }
        }

        #endregion

        #endregion


        private bool CheckIfMatch( string workingLine, string regularExpression )
        {
            Regex r = new Regex( regularExpression );
            bool result = r.Match( workingLine ).Success;

            return result;
        }


        private string GetTeamName( ref string workingLine )
        {
            string teamName = GetDataSection( ref workingLine, RegularExpressions.EVENT_TEAM_POINTCAPTURED );
            teamName = teamName.Replace( "Team \"", "" );
            teamName = teamName.Substring( 0, teamName.IndexOf( "\"" ) );
            return teamName;
        }

        private int GetCPNumber( ref string workingLine )
        {
            int returnNumber = 0;

            string cpNumber = GetDataSection( ref workingLine, RegularExpressions.WORLD_CPNUMBER );
            cpNumber = cpNumber.Replace( "(cp \"", "" );
            cpNumber = cpNumber.Replace( "\")", "" );

            returnNumber = Convert.ToInt32( cpNumber );

            return returnNumber;
        }

        private string GetCPName( ref string workingLine )
        {
            string cpName = GetDataSection( ref workingLine, RegularExpressions.WORLD_CPNAME );
            cpName = cpName.Replace( "(cpname \"", "" );
            cpName = cpName.Replace( "\")", "" );
            cpName = cpName.Trim();

            return cpName;
        }

        private string GetObject( ref string workingLine )
        {
            string objectName = GetDataSection( ref workingLine, RegularExpressions.WORLD_OBJECT );

            objectName = objectName.Replace( "(object \"", "" );
            objectName = objectName.Replace( "\")", "" );
            objectName = objectName.Trim();

            return objectName;
        }

        private string GetWeapon( ref string workingLine )
        {
            string weaponName = GetDataSection( ref workingLine, RegularExpressions.WORLD_WEAPON );

            weaponName = weaponName.Replace( "(weapon \"", "" );
            weaponName = weaponName.Replace( "\")", "" );
            weaponName = weaponName.Trim();

            return weaponName;
        }

        //(objectowner "|RES|Stinkfist<26><STEAM_0:1:229390><Blue>") 
        private Player GetObjectOwner( ref string workingLine )
        {
            string ownerPlayerId;

            try
            {
                string objectOwner = GetDataSection( ref workingLine, RegularExpressions.WORLD_OBJECTOWNER );

                objectOwner = objectOwner.Replace( "(objectowner ", "" );
                objectOwner = objectOwner.Replace( ")", "" );
                objectOwner = objectOwner.Trim();

                ownerPlayerId = GetPlayer( ref objectOwner, false );

            }
            catch
            {
                // hack for someone destroying their own object
                ownerPlayerId = _actingPlayer.PlayerId;

            }

            // hack for someone destroying their own object
            if ( ownerPlayerId == "" )
                ownerPlayerId = _actingPlayer.PlayerId;

            Player ownerPlayer = (Player) _playerList[ ownerPlayerId ];

            return ownerPlayer;
        }

        private string GetCurrentClassName( string playerId )
        {
            string className = string.Empty;

            Player currentPlayer = (Player) _playerList[ playerId ];
            className = currentPlayer.CurrentClass;

            return className;
        }

        private DateTime GetDateTime( ref string workingLine )
        {

            string tempLine = GetDataSection( ref workingLine, RegularExpressions.DATETIME );

            tempLine = tempLine.Replace( "L ", "" );
            tempLine = tempLine.Replace( "- ", "" );

            workingLine = workingLine.Remove( 0, 2 );

            return Convert.ToDateTime( tempLine );

        }

        private string GetDataSection( ref string workingLine, string dataRegularExpression )
        {
            string tempLine = string.Empty;

            try
            {
                Regex r = new Regex( dataRegularExpression );
                int startIndex = -1;
                int length = -1;

                System.Text.RegularExpressions.Match m = r.Match( workingLine );

                if ( m.Success )
                {
                    startIndex = m.Index;
                    length = m.Length;

                    tempLine = workingLine.Substring( startIndex, length );

                    workingLine = workingLine.Replace( tempLine, "" );  // Remove date/time
                    workingLine = workingLine.Trim();
                }

            }
            catch
            {

            }

            return tempLine;
        }


        #endregion

        #region Private Member Functions

        #endregion
    }
}

#region VSS Log

/*
 * $Log: $
 */

#endregion VSS Log